using System.Collections.Immutable;
using DimensionsHelper.LanguageService.Symbols;
using DimensionsHelper.LanguageService.Syntax;

namespace DimensionsHelper.LanguageService;

public class AnalysisDouble : AnalysisExpression
{
    internal AnalysisDouble(DoubleLiteral source, AnalysisNode? parent) :
        base(AnalysisBoundKinds.Literal, source, parent)
    {
        Syntax = source;
        Value = source.Value;
        Bind(ValueTypeSymbol.Double);
    }


    public override DoubleLiteral Syntax { get; }


    /// <summary>
    ///     浮点数数值
    /// </summary>
    public double Value { get; }


    public override AnalysisExpression? WithImplicitlyConversion(ValueTypeSymbol targetType)
    {
        if (targetType == ValueTypeSymbol.Double || targetType == ValueTypeSymbol.Any)
        {
            return this;
        }

        if (targetType == ValueTypeSymbol.Long)
        {
            return AnalysisNodeFactory.Integer(NodeConverter.ToInteger(Syntax, (int)Value), Parent);
        }

        if (targetType == ValueTypeSymbol.Boolean)
        {
            return AnalysisNodeFactory.Boolean(NodeConverter.ToBoolean(Syntax, Value != 0), Parent);
        }

        if (targetType == ValueTypeSymbol.Date &&
            Value >= DateTime.MinValue.ToBinary() &&
            Value <= DateTime.MaxValue.ToBinary())
        {
            return AnalysisNodeFactory.Date(Syntax, DateTime.FromOADate(Value), Parent);
        }

        return null;
    }


    public override IEnumerable<AnalysisNode> GetChildren()
    {
        return ImmutableArray<AnalysisNode>.Empty;
    }

    internal override void AddChild(AnalysisNode child)
    {
        throw new NotSupportedException("AnalysisDouble cannot have children.");
    }
}


public static partial class AnalysisNodeFactory
{
    /// <summary>
    /// 创建一个浮点数常量
    /// </summary>
    /// <param name="syntaxNode">原始语法节点</param>
    /// <param name="parent">父节点</param>
    public static AnalysisDouble Double(DoubleLiteral syntaxNode, AnalysisNode? parent)
    {
        return new AnalysisDouble(syntaxNode, parent);
    }
}